//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <elasys_server.h>
#include <wincetypes.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "CBasicFileSystem.h"
#define IncrementDllLockCount() do {} while(0)
#define DecrementDllLockCount() do {} while(0)
#include "_CKtfsFileSystem.cpp"
#include "CBasicDirectory.h"
#include "CBasicFile.h"

CKtfsFileSystem::CKtfsFileSystem()
{
}

CKtfsFileSystem::CKtfsFileSystem(wchar_t *wcsDisk)
{
    wchar_t *wcsDiskName = (wchar_t *)malloc(sizeof(wchar_t) * (wcslen(wcsDisk)+1));
    assert(wcsDiskName);
    wcscpy(wcsDiskName, wcsDisk);
    m_wstrDisk = wcsDiskName;
}

CKtfsFileSystem::~CKtfsFileSystem()
{
    free((void *)m_wstrDisk);
}

ECode CKtfsFileSystem::Sync()
{
    return NOERROR;
}

ECode CKtfsFileSystem::GetRoot(
    /* [out] */ IBasicDirectory * * piRoot)
{
    if (piRoot == NULL) {
        return E_INVALID_ARGUMENT;
    }
#if 0
    wchar_t *wcsEnv = _wgetenv(L"SYSTEM_BIN_PATH");
    assert(wcsEnv);
    wchar_t *pFind = wcspbrk(wcsEnv, L"\\/");
    if (pFind) {
        *pFind = '\0';
    }
    WString esEnv = WString::AllocString(wcsEnv);
#endif

    CBasicDirectory *pBasicDir = new CBasicDirectory(m_wstrDisk);
    if (pBasicDir == NULL) {
        return E_OUT_OF_MEMORY;
    }
    pBasicDir->AddRef();
    *piRoot = pBasicDir;
//    WString::FreeString(esEnv);
    return NOERROR;
}

ECode CKtfsFileSystem::Lookup(
    /* [in] */ WString pathname,
    /* [out] */ IBasicFile * * piBasicFile)
{
    if (pathname.IsNull() || !piBasicFile) {
        return E_INVALID_ARGUMENT;
    }

    WStringBuf_<MAX_PATH> esPathName;
    esPathName.Copy(m_wstrDisk);
    esPathName.Append(L"\\");
    esPathName.Append(pathname);
    DWORD attr = GetFileAttributesW((wchar_t *)esPathName.GetPayload());
    if (attr == 0xffffffff) {  //file does not exist
        return ECODE_FROM_ERRNO(ESRCH);
    }
    if (attr & FILE_ATTRIBUTE_DIRECTORY) {
        CBasicDirectory *pBasicDir = new CBasicDirectory(esPathName);
        if (pBasicDir == NULL) {
            return E_OUT_OF_MEMORY;
        }
        pBasicDir->AddRef();
        *piBasicFile = (IBasicFile *)pBasicDir;
        return NOERROR;
    }
    else {
        CBasicFile *pBasicFile = new CBasicFile(esPathName, TRUE, TRUE);
        if (pBasicFile == NULL) {
            return E_OUT_OF_MEMORY;
        }
        pBasicFile->AddRef();
        *piBasicFile = pBasicFile;
        return NOERROR;
    }
}

ECode CKtfsFileSystem::GetStat(
    /* [out] */ FileSystemStat * pFileSystemStat)
{
    if (NULL == pFileSystemStat)
        return E_INVALID_ARGUMENT;
    UINT64 total_size, free_size;

    if (!GetDiskFreeSpaceExW(
        NULL,
        NULL,
        (PULARGE_INTEGER)&total_size,
        (PULARGE_INTEGER)&free_size)) {

        return ECODE_FROM_WIN32(GetLastError());
    }

    pFileSystemStat->clusterSize = 4096;
    pFileSystemStat->totalClusters = (UINT)(total_size / pFileSystemStat->clusterSize);
    pFileSystemStat->freeClusters = (UINT)(free_size / pFileSystemStat->clusterSize);
    pFileSystemStat->fatType = FatType_FAT32;
    return NOERROR;
}

ECode CKtfsFileSystem::BindDriver(
    /* [in] */ WString wstrDevName)
{
    return NOERROR;
}

ECode CKtfsFileSystem::UnbindDriver()
{
    return NOERROR;
}
